package com.ay.selfservicemachine.http.websocket;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class SocketClient {
    Handler handler=new Handler(Looper.getMainLooper());

    public int from = 0;
    public WebSocket webSocket;

    String url;
    ClientAction clientAction;

    public int getFrom() {
        return from;
    }


    public WebSocket getWebSocket() {
        return webSocket;
    }

    public SocketClient(int from, String url,ClientAction clientAction) {
        this.from = from;
        this.url=url;
        this.clientAction=clientAction;
        this.webSocket = getClient();
    }

    private WebSocket getClient() {
        url=url.replaceAll("\"|\\\\","");
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .callTimeout(5, TimeUnit.MINUTES)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .build();
        WebSocket webSocket = okHttpClient.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosed(webSocket, code, reason);
            }

            @Override
            public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosing(webSocket, code, reason);
            }

            @Override
            public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                startReconnection();
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) {
                super.onMessage(webSocket, text);
                handler.post(()->{
                    clientAction.callbackMessage(text);
                });
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull ByteString bytes) {
                super.onMessage(webSocket, bytes);
                handler.post(()->{
                    clientAction.callbackMessage(bytes);
                });
            }

            @Override
            public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) {
                super.onOpen(webSocket, response);
                cancelTimer();
                startPing(webSocket);
            }
        });
        return webSocket;
    }

    public void cancel() {
        cancelPing();
        cancelReconnection();
        if (webSocket != null) {
            webSocket.close(1000,"");
        }
    }

    public void cancelTimer(){
        cancelPing();
        cancelReconnection();
    }

    public interface ClientAction {
        default void callbackMessage(String message){};
        default void callbackMessage(ByteString bytes){};
    }


    //////////////心跳发送1秒一次////////////
    Timer pingTimer = new Timer();
    public void startPing(WebSocket webSocket) {
        if (pingTimer != null) {
            pingTimer.cancel();
        }
        pingTimer=new Timer();
        pingTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                webSocket.send(getPingValue());
            }
        }, 0, 1000);
    }

    public void cancelPing() {
        if (pingTimer != null) {
            pingTimer.cancel();
        }
    }

    ///////////////断线重新链接计时器///////////////
    Timer reconnectionTimer = new Timer();
    public void startReconnection() {
        if (reconnectionTimer != null) {
            reconnectionTimer.cancel();
        }
        reconnectionTimer=new Timer();
        reconnectionTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                webSocket = getClient();
            }
        }, 5000);
    }

    public void cancelReconnection() {
        if (reconnectionTimer != null) {
            reconnectionTimer.cancel();
        }
    }

    //心跳发送内容
    public String getPingValue() {
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("type", "pong");
        } catch (JSONException v) {

        }
        return jsonObject.toString();
    }


}
